/*!
 * @file pawirr.hh
 * @brief Kontener wskaźników na moduły.
 */

#ifndef __ENGINE_PAWIRR_HH
#define __ENGINE_PAWIRR_HH

#include <sstream>
#include <string>
#include <fstream>

#include <SDL/SDL.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glext.h>

#include "engine/log.hh"
#include "engine/cmd.hh"

#include "language.hh"
#include "path.hh"

#include "engine/basic/inifile.hh"
#include "engine/basic/texture.hh"

#include "engine/moduleBase.hh"
#include "engine/key/moduleKeyboard.hh"
#include "engine/gfx/moduleGraphic.hh"
#include "engine/set/moduleSet.hh"
#include "engine/tmp/moduleTemplate.hh"
#include "engine/mc/moduleModes.hh"

#include "engine/modeBase.hh"
#include "modes/console/modeConsole.hh"
#include "modes/world/modeWorld.hh"


/*!
 * @brief Typy kończenia programu
 * QNORMAL - dokończenie wykonywania pętli, zwolnienie zasobów
 * QBRUTAL - natychmiastowe zakończenie działania
 */
enum _quit_type {
	QNORMAL, QBRUTAL
};

/*!
 * @brief Klasa z elementami statycznymi dostępnymi globalnie.
 * Centrum całego silnika.
 */
class pawirr {
public:

	/*!
	 * @brief Inicjalizacja modułów i trybów
	 */
	static void init();

	/*!
	 * @brief Start pętli
	 */
	static void loop();

	/*!
	 * @brief Zwalnianie pamięci
	 * @param et Sposób zakończenia programu
	 */
	static void quit(_quit_type et);

	/*!
	 * @brief Klawiatura
	 */
	static moduleKeyboard *keyboard;

	/*!
	 * @brief Grafika
	 */
	static moduleGraphic *graphic;

	/*!
	 * @brief Baza danych - Ustawienia
	 */
	static moduleSet *set;

	/*!
	 * @brief Wykaz wszystkich trybów
	 */
	static moduleModes *m;

	/*!
	 * @brief Obiekty tymczasowe
	 */
	static moduleTemplate *temp;

	/*!
	 * @brief Pliki pawirr/config.ini
	 */
	static inifile *config;

	/*!
	 * @brief Zwraca moduł po nazwie w stringu
	 * @param name Nazwa szukanego modułu
	 * @return Wskaźnik na moduł lub NULL
	 */
	static moduleBase *getModuleByName(std::string name);

	/*!
	 * @brief Zwraca tryb po nazwie w stringu
	 * @param name Nazwa szukanego modułu
	 * @return Wskaźnik na moduł lub NULL
	 */
	static modeBase *getModeByName(std::string name);

	/*!
	 * @brief Pobieranie czasu rozpoczęcia pętli
	 * @return czas rozpoczęcia malowania aktualnej klatki
	 */
	static unsigned long int getTime();

	/*!
	 * @brief Pobieranie ilości wyrenderowanych klatek
	 * @return Ilość wyrenderowanych klatek
	 */
	static unsigned long int getFPSCount();

private:

	/*!
	 * @brief Konstruktor uniemożliwiający tworzenie obiektów
	 * @return
	 */
	pawirr();

	/*!
	 * @brief Czas
	 */
	static long unsigned int currentTime;

	/*!
	 * @brief Ilość okrążeń głównej pętli
	 */
	static long unsigned int FPSCount;

	/*!
	 * @brief Inicjalizacja wszystkiego
	 */
	static void boot();

	/*!
	 * @brief Startowanie SDLa
	 */
	static void init_sdl();

	/*!
	 * @brief Lista trybów
	 */
	static std::list<modeBase*> *listMode;

	/*!
	 * @brief Lista modułów
	 */
	static std::list<moduleBase*> *listModule;

	/*!
	 * @brief Wczytywanie modułu
	 * @param ptn Wskaźnik na zmienną do nadpisania
	 */
	template<typename T>
	static void sys_loadModule(T** ptn) {

		(*ptn) = new T;
		(*ptn)->init();

		pawirr::listModule->push_back(*ptn);
	}

	/*!
	 * @brief Wczytywanie trybu
	 * @param ptn Wskaźnik na zmienną do nadpisania
	 */
	template<typename T>
	static void sys_loadMode(T** ptn) {

		(*ptn) = new T;
		(*ptn)->init();

		pawirr::listMode->push_back(*ptn);
	}

	/*!
	 * @brief Czy pętlić?
	 */
	static bool isLoop;

	/*!
	 * @brief Funkcja głównego wątku
	 * @return stan
	 */
	static int mainLoop();


};

#else
class pawirr;
#endif
